package com.zhadafei.mvnbook.account.captcha;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.imageio.ImageIO;
import org.springframework.beans.factory.InitializingBean;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;

public class AccountCaptchaServiceImpl implements AccountCaptchaService,
		InitializingBean {
	private DefaultKaptcha producer;

	// AccountCaptchaServiceImpl实现了SpringFramework的InitializingBean接口,
	// 该接口定义了一个方法afterPropertiesSet(); 该方法会被SpringFramework初始化对象的时候调用
	// 代码清单中使用该方法初始化验证码生成器producer,并且为producer提供了默认的配置
	public void afterPropertiesSet() throws Exception {
		producer = new DefaultKaptcha();
		producer.setConfig(new Config(new Properties()));
	}

	private Map<String, String> captchaMap = new HashMap<String, String>();
	private List<String> preDefinedTexts;
	private int textCount = 0;

	/**
	 * 生成随机验证码
	 */
	public String generateCaptchaKey() {
		String key = RandomGenerator.getRandomString();// 生成一个随机验证码主键 标示验证码图片
		String value = getCaptchaText();// 验证码字符串
		captchaMap.put(key, value);// 存储起来以备将来校验
		return key;
	}

	/**
	 * 通过验证码生成图片
	 */
	public byte[] generateCaptchaImage(String captchaKey)
			throws AccountCaptchaException {
		String text = captchaMap.get(captchaKey);
		if (text == null) {
			throw new AccountCaptchaException("Captch key'" + captchaKey
					+ "'notfound!");
		}
		BufferedImage image = producer.createImage(text);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		try {
			ImageIO.write(image, "jpg", out);
		} catch (IOException e) {
			throw new AccountCaptchaException(
					"Failed to write captcha stream！", e);
		}
		return out.toByteArray();
	}

	/**
	 * 验证传输过来的验证码跟缓存起来的是否一致
	 */
	public boolean validateCaptcha(String captchaKey, String captchaValue)
			throws AccountCaptchaException {
		String text = captchaMap.get(captchaKey);
		if (text == null) {
			throw new AccountCaptchaException("Captch key'" + captchaKey
					+ "'notfound！");
		}
		if (text.equals(captchaValue)) {
			captchaMap.remove(captchaKey);
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 手工设置验证码值
	 */
	public List<String> getPreDefinedTexts() {
		return preDefinedTexts;
	}

	/**
	 * 手工设置验证码值
	 */
	public void setPreDefinedTexts(List<String> preDefinedTexts) {
		this.preDefinedTexts = preDefinedTexts;
	}

	/**
	 * 获取验证码字符串,如果预设置了就直接从其中取,不自动生成了,否则随机生成一个作为值,这样设置的好处就是便于测试,
	 * 使验证码字符串可知,可控。
	 * 
	 * @return
	 */
	private String getCaptchaText() {
		if (preDefinedTexts != null && !preDefinedTexts.isEmpty()) {
			String text = preDefinedTexts.get(textCount);
			textCount = (textCount + 1) % preDefinedTexts.size();
			return text;
		} else {
			return producer.createText();
		}
	}

}